use std::ops::Deref;

use shared::*;
use wasm_bindgen_futures::spawn_local;
use ybc::{Button, Container, Card, CardContent, CardFooter, CardHeader, Content};
use yew::{prelude::*, suspense::*};

use crate::api;
use crate::dialog::AddProfileDialog;

#[derive(Properties, PartialEq)]
pub struct Props {
    pub profile: NetemProfile,
}

#[function_component]
pub fn ProfileCard(props: &Props) -> Html {
    let profile_state = use_state(|| props.profile.clone());

    let name = format!(
        "{}{}",
        profile_state.name,
        if profile_state.active {
            " - 已启用"
        } else {
            ""
        }
    );
    let desc = netem_cfg_description(&profile_state.cfgs);

    let on_toggle_profile = {
        let profile_state = profile_state.clone();
        Callback::from(move |_| {
            let profile_state = profile_state.clone();
            spawn_local(async move {
                let mut profile = profile_state.deref().clone();
                profile.active = !profile.active;
                match api::update_profile(profile).await {
                    Ok(profile) => {
                        profile_state.clone().set(profile);
                    },
                    Err(err) => {
                        log::error!("toggle profile error: {}", err);
                    },
                };
            });
        })
    };
    let on_delete_profile = {
        let profile_state = profile_state.clone();
        Callback::from(move |_| {
            let profile_state = profile_state.clone();
            spawn_local(async move {
                match api::delete_profile(profile_state.deref().clone()).await {
                    Ok(()) => {
                    },
                    Err(err) => {
                        log::error!("delete profile error: {}", err);
                    },
                };
            });
        })
    };
    html! {
        <Container classes={classes!("mx-4")}>
            <Card>
                <CardHeader>
                    <p class={"card-header-title"}>{name}</p>
                </CardHeader>
                <CardContent>
                    <Content>
                        {desc}
                    </Content>
                </CardContent>
                <CardFooter classes={classes!("is-justify-content-center")}>
                    <ToggleButton profile={profile_state.deref().clone()} onclick={on_toggle_profile}/>
                    {                    
                        if !profile_state.active {
                            html! {<>
                                <Button>{"编辑"}</Button>
                                <Button onclick={on_delete_profile}>{"删除"}</Button>
                            </>}
                        } else {
                            html! { <></> }
                        }
                    }
                </CardFooter>
            </Card>
        </Container>
    }
}

#[derive(Properties, PartialEq)]
struct ToggleButtonProps {
    profile: NetemProfile,
    onclick: Callback<()>,
}

#[function_component]
fn ToggleButton(props: &ToggleButtonProps) -> Html {
    let text = if props.profile.active {
        "关闭"
    } else {
        "启用"
    };
    let onclick = {
        let onclick = props.onclick.clone();
        move |_: MouseEvent| {
            onclick.emit(());
        }
    };
    html! {
        <Button {onclick}>{text}</Button>
    }
}

#[function_component]
pub fn ProfileCardList() -> HtmlResult {
    let profiles = use_future(api::get_profiles)?;
    let profiles = match *profiles {
        Ok(ref profiles) => {
            html! {
                <div class="is-flex">
                    { profiles.iter().map(|p| html! { <ProfileCard profile={p.clone()} /> }).collect::<Html>() }
                    <AddProfileButton />
                </div>
            }
        }
        Err(ref err) => {
            log::info!("err: {}", err);
            html! { <p>{ "Error: " } { err }</p> }
        }
    };
    Ok(profiles)
    /*
    let profiles = vec![
        NetemProfile {
            name: String::from("f1"),
            ..Default::default()
        },
        NetemProfile {
            name: String::from("f3"),
            ..Default::default()
        },
    ];
    */
}

#[function_component]
pub fn AddProfileButton() -> Html {
    html! {
        <>
            // <Button {onclick}>{ "添加模拟网络" }</Button>
            <AddProfileDialog />
        </>
    }
}

fn netem_cfg_description(cfgs: &[NetemConfig]) -> String {
    let mut desc = String::with_capacity(128);
    for i in 0..cfgs.len() {
        if i > 0 {
            desc.push_str(", ");
        }
        match cfgs[i] {
            NetemConfig::Delay(DelayConfig::Value(val)) => {
                desc.push_str(&format!("延迟：{} ms", val));
            }
            NetemConfig::Jitter(JitterConfig::Stable(val)) => {
                desc.push_str(&format!("抖动：{} ms", val));
            }
            NetemConfig::Jitter(JitterConfig::Burst { burst, interval }) => {
                desc.push_str(&format!("突发到达：{} ms(间隔 {} s)", burst, interval));
            }
            NetemConfig::Loss(LossConfig::Stable(val)) => {
                desc.push_str(&format!("丢包率：{:.2} %", val * 100.0));
            }
            NetemConfig::Loss(LossConfig::Poisson(val)) => {
                desc.push_str(&format!("丢包率(PPP)：{:.2} %", val * 100.0));
            }
        }
    }
    desc
}
